﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks.Schedulers;
using MishraReader.Entities;

namespace MishraReader.AppServices
{
    public enum ShareServiceJobState
    {
        Working,
        Completed,
        Failure
    }

    public class ShareServiceJobStateChangedEventArgs : EventArgs
    {
        public ShareServiceJobStateChangedEventArgs(ShareServiceJob job, ShareServiceJobState state)
        {
            Job = job;
            State = state;
        }

        public ShareServiceJob Job { get; private set; }
        public ShareServiceJobState State { get; private set; }
    }

    public delegate void ShareServiceJobStateChangedHandler(object sender, ShareServiceJobStateChangedEventArgs e);

    public class ShareServiceJob
    {
        public Item Item { get; set; }
        public string Message { get; set; }
        public ShareServiceAccount ServiceAccount { get; set; }
    }

    internal class ShareServiceManager : IShareServiceManager
    {
        public event ShareServiceJobStateChangedHandler JobStateChanged;
        private readonly LimitedConcurrencyLevelTaskScheduler _scheduler = new LimitedConcurrencyLevelTaskScheduler(1);

        /// <summary>
        /// </summary>
        /// <param name="serviceAccount"> </param>
        /// <param name="message"> </param>
        /// <param name="item"> </param>
        public void AddShareJob(ShareServiceAccount serviceAccount, String message, Item item)
        {
            var job = new ShareServiceJob {ServiceAccount = serviceAccount, Message = message, Item = item};

            var task = new Task(
                () =>
                    {
                        OnJobStateChanged(new ShareServiceJobStateChangedEventArgs(job, ShareServiceJobState.Working));
                        job.ServiceAccount.ServicePackage.Service.Share(job.ServiceAccount, message, item);
                    });

            task.ContinueWith(
                op =>
                OnJobStateChanged(op.Exception == null
                                      ? new ShareServiceJobStateChangedEventArgs(job, ShareServiceJobState.Completed)
                                      : new ShareServiceJobStateChangedEventArgs(job, ShareServiceJobState.Failure)));

            task.Start(_scheduler);
        }

        /// <summary>
        ///   Raise in async context !
        /// </summary>
        /// <param name="e"> </param>
        protected void OnJobStateChanged(ShareServiceJobStateChangedEventArgs e)
        {
            if (JobStateChanged != null)
                JobStateChanged(this, e);
        }
    }
}